package com.zdp.sources.config;

import com.zaxxer.hikari.HikariDataSource;
import com.zdp.sources.common.db.DBTypeEnum;
import com.zdp.sources.common.db.DynamicDataSource;
import com.zdp.sources.resource.CustomProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

/**
 * <h1>数据源配置支持多数据源</h1>
 * @author sesshomaru
 * @date 2022/2/28
 */
@Configuration
@Slf4j
public class DataSourceConfig {

    private CustomProperties customProperties;

    public DataSourceConfig(CustomProperties customProperties) {
        this.customProperties = customProperties;
    }

    private HikariDataSource builderHikariDataSource(String jdbcUrl, String username, String password,
                                                     long connectionTimeout, int minimumIdle, int maximumPoolSize, boolean autoCommit,
                                                     long idleTimeout, String poolName, long maxLifetime, String connectionTestQuery) {
        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource.setJdbcUrl(jdbcUrl);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        dataSource.setConnectionTimeout(connectionTimeout);
        dataSource.setMinimumIdle(minimumIdle);
        dataSource.setMaximumPoolSize(maximumPoolSize);
        dataSource.setAutoCommit(autoCommit);
        dataSource.setIdleTimeout(idleTimeout);
        dataSource.setPoolName(poolName);
        dataSource.setMaxLifetime(maxLifetime);
        dataSource.setConnectionTestQuery(connectionTestQuery);
        return dataSource;
    }

    @Bean(name = "master1")
    public DataSource master1() {
        CustomProperties.BasisHikariDateSource dateSource = customProperties.getDb().getMaster1();
        HikariDataSource hikariDataSource = builderHikariDataSource(dateSource.getJdbcUrl(), dateSource.getUsername(), dateSource.getPassword(),
                dateSource.getConnectionTimeout(), dateSource.getMinimumIdle(), dateSource.getMaximumPoolSize(), dateSource.getAutoCommit(),
                dateSource.getIdleTimeout(), dateSource.getPoolName(), dateSource.getMaxLifetime(), dateSource.getConnectionTestQuery());
        log.info("数据源[{}]创建成功!~", "master1");
        return hikariDataSource;
    }

    @Bean(name = "slave1")
    public DataSource slave1() {
        CustomProperties.BasisHikariDateSource dateSource = customProperties.getDb().getSlave1();
        HikariDataSource hikariDataSource = builderHikariDataSource(dateSource.getJdbcUrl(), dateSource.getUsername(), dateSource.getPassword(),
                dateSource.getConnectionTimeout(), dateSource.getMinimumIdle(), dateSource.getMaximumPoolSize(), dateSource.getAutoCommit(),
                dateSource.getIdleTimeout(), dateSource.getPoolName(), dateSource.getMaxLifetime(), dateSource.getConnectionTestQuery());
        log.info("数据源[{}]创建成功!~", "slave1");
        return hikariDataSource;
    }

    @Bean(name = "slave2")
    public DataSource slave2() {
        CustomProperties.BasisHikariDateSource dateSource = customProperties.getDb().getSlave2();
        HikariDataSource hikariDataSource = builderHikariDataSource(dateSource.getJdbcUrl(), dateSource.getUsername(), dateSource.getPassword(),
                dateSource.getConnectionTimeout(), dateSource.getMinimumIdle(), dateSource.getMaximumPoolSize(), dateSource.getAutoCommit(),
                dateSource.getIdleTimeout(), dateSource.getPoolName(), dateSource.getMaxLifetime(), dateSource.getConnectionTestQuery());
        log.info("数据源[{}]创建成功!~", "slave2");
        return hikariDataSource;
    }

    /**
     * <h2>动态数据源</h2>
     * @return DataSource
     */
    @Bean(value = "myRoutingDataSource")
    public DataSource multipleDataSource(@Qualifier("master1") DataSource masterDataSource,
                                         @Qualifier("slave1") DataSource slave1DataSource,
                                         @Qualifier("slave2") DataSource slave2DataSource) {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put(DBTypeEnum.MASTER, masterDataSource);
        targetDataSources.put(DBTypeEnum.SLAVE1, slave1DataSource);
        targetDataSources.put(DBTypeEnum.SLAVE2, slave2DataSource);

        dynamicDataSource.setDefaultTargetDataSource(masterDataSource);
        dynamicDataSource.setTargetDataSources(targetDataSources);
        return dynamicDataSource;
    }
}
